#include <stdio.h>
#include <string.h>
#include "../hdr/big_math.h"

#define MAXWORD 0xFFFFFFFF


big_int ZERO;

// initializes the ZERO big integer. this is returned in the bit_mult function
void lib_init() {
	int i;
	for (i=0; i < LENGTH; i++) {
		ZERO.words[i] = 0;
	}
}


/*
 *	init(bit_int, char, int)
 *	initializes a big_int value using a Hex String as input
 *	expected input has each hex word separated by a '-'
 *	e.g. "37A983-478B8EC7-7398790F-FD8E9739"
 *
 *	length is the number of characters in the string
 */
void init_big_int (big_int* result, char* input) {
	register int i;

	//char* stringCursor = input;
	register int num_input_words = num_words(input);

	char* word = strtok(input, "-");

	for (i = num_input_words-1; i >= 0 && word != NULL; i--) {
		sscanf(word, "%x", &(result->words[i]) );
		word = strtok(NULL, "-");
	}

	for (i = num_input_words; i <  LENGTH; i++) {
		result->words[i] = 0;
	}


	return;
}



//compute the number of words presented in the input string
int num_words(char* input) {
	int numDashes = 0;
	int i = 0;
	while (input[i] != '\0') {
                if ( input[i] == '-' ) {
	                numDashes++;
		}
		i++;
	}

	return numDashes+1;
}

//print formatted version of a big int
void print_big_int(const big_int *toprint) {

	register int i;
	for (i = LENGTH-1; i >=1; i--) {
		printf("%08x-", toprint->words[i]);
	}
	printf("%08x\n", toprint->words[0]);
	return;
}

// set the value of dest to the value of source
void assign(big_int * dest, const big_int*  source) {
	register int i;

	for (i = 0; i< LENGTH; i++) {
		dest->words[i] = source->words[i];
	}
}


//return true if op1 is less than op2, otherwise false
int less_than(const big_int* op1, const big_int* op2) {
	register int i;

	for (i = LENGTH-1; i >= 0; i--) {
		if (op1->words[i] == 0 && op2->words[i] != 0)
			return 1; // true
		if (op1->words[i] != 0 && op2->words[i] == 0)
			return 0; // false
		if (op1->words[i] != 0 && op2->words[i] != 0)
			return op1->words[i] < op2->words[i];
		// if op 1 != 0 && op2 == 0 return false
		// if op 1 == 0 && op2 != 0 return true
		// if op 1 != 0 && op2 != 0 return op1 < op 2
	}
}

// add together op1 and op2 and store it in result.
void add(big_int *result, const big_int* op1, const big_int* op2) {

	//register int i;
	register unsigned int carry = 0;
	register unsigned int temp1, temp2;
	register unsigned int tempres = 0;
	register int nextcarry = 0;


/*
	for (i = 0; i < LENGTH; i++) {
		//result =  op1->words[i] + op2->words[i] + carry;
		temp1 = op1->words[i];
		temp2 = op2->words[i];

		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));

		carry = nextcarry;
		nextcarry = 0;

		result->words[i] = tempres;
	}
*/

/*
	temp1 = op1->words[0];
	temp2 = op2->words[0];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[0] = tempres;
	carry = nextcarry;
	nextcarry = 0;

	temp1 = op1->words[1];
	temp2 = op2->words[1];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[1] = tempres;
	carry = nextcarry;
	nextcarry = 0;

	temp1 = op1->words[2];
	temp2 = op2->words[2];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[2] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[3];
	temp2 = op2->words[3];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[3] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[4];
	temp2 = op2->words[4];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[4] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[5];
	temp2 = op2->words[5];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[5] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[6];
	temp2 = op2->words[6];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[6] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[7];
	temp2 = op2->words[7];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[7] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[8];
	temp2 = op2->words[8];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[8] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[9];
	temp2 = op2->words[9];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[9] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[10];
	temp2 = op2->words[10];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[10] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[11];
	temp2 = op2->words[11];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[11] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[12];
	temp2 = op2->words[12];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[12] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[13];
	temp2 = op2->words[13];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[13] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[14];
	temp2 = op2->words[14];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[14] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[15];
	temp2 = op2->words[15];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[15] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[16];
	temp2 = op2->words[16];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[16] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[17];
	temp2 = op2->words[17];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[17] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[18];
	temp2 = op2->words[18];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[18] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[19];
	temp2 = op2->words[19];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[19] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[20];
	temp2 = op2->words[20];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[20] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[21];
	temp2 = op2->words[21];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[21] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[22];
	temp2 = op2->words[22];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[22] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[23];
	temp2 = op2->words[23];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[23] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[24];
	temp2 = op2->words[24];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[24] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[25];
	temp2 = op2->words[25];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[25] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[26];
	temp2 = op2->words[26];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[26] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[27];
	temp2 = op2->words[27];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[27] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[28];
	temp2 = op2->words[28];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[28] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[29];
	temp2 = op2->words[29];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[29] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[30];
	temp2 = op2->words[30];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[30] = tempres;
	carry = nextcarry;
	nextcarry = 0;


	temp1 = op1->words[31];
	temp2 = op2->words[31];
		__asm__ volatile ("ADDS  %0, %1, %2\n\t" :
			"=r"(tempres) :
			"r"(temp1), "r"(temp2)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
			: "=r"(nextcarry));
        __asm__ volatile ("ADDS  %0, %0, %2\n\t"
			: "=r"(tempres)
			: "0"(tempres), "r"(carry)  );
		__asm__ volatile ("MOVCS %0, #1\n\t"
                        : "=r"(nextcarry));
	result->words[31] = tempres;
	carry = nextcarry;
	nextcarry = 0;


*/




	temp1 = op1->words[0];
	temp2 = op2->words[0];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[0] = tempres;


	temp1 = op1->words[1];
	temp2 = op2->words[1];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[1] = tempres;

	temp1 = op1->words[2];
	temp2 = op2->words[2];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[2] = tempres;

	temp1 = op1->words[3];
	temp2 = op2->words[3];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[3] = tempres;

	temp1 = op1->words[4];
	temp2 = op2->words[4];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[4] = tempres;

	temp1 = op1->words[5];
	temp2 = op2->words[5];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[5] = tempres;

	temp1 = op1->words[6];
	temp2 = op2->words[6];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[6] = tempres;

	temp1 = op1->words[7];
	temp2 = op2->words[7];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[7] = tempres;

	temp1 = op1->words[8];
	temp2 = op2->words[8];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[8] = tempres;

	temp1 = op1->words[9];
	temp2 = op2->words[9];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[9] = tempres;

	temp1 = op1->words[10];
	temp2 = op2->words[10];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[10] = tempres;

	temp1 = op1->words[11];
	temp2 = op2->words[11];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[11] = tempres;

	temp1 = op1->words[12];
	temp2 = op2->words[12];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[12] = tempres;

	temp1 = op1->words[13];
	temp2 = op2->words[13];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[13] = tempres;

	temp1 = op1->words[14];
	temp2 = op2->words[14];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[14] = tempres;

	temp1 = op1->words[15];
	temp2 = op2->words[15];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[15] = tempres;

	temp1 = op1->words[16];
	temp2 = op2->words[16];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[16] = tempres;

	temp1 = op1->words[17];
	temp2 = op2->words[17];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[17] = tempres;

	temp1 = op1->words[18];
	temp2 = op2->words[18];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[18] = tempres;

	temp1 = op1->words[19];
	temp2 = op2->words[19];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[19] = tempres;

	temp1 = op1->words[20];
	temp2 = op2->words[20];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[20] = tempres;

	temp1 = op1->words[21];
	temp2 = op2->words[21];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[21] = tempres;

	temp1 = op1->words[22];
	temp2 = op2->words[22];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[22] = tempres;

	temp1 = op1->words[23];
	temp2 = op2->words[23];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[23] = tempres;

	temp1 = op1->words[24];
	temp2 = op2->words[24];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[24] = tempres;

	temp1 = op1->words[25];
	temp2 = op2->words[25];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[25] = tempres;

	temp1 = op1->words[26];
	temp2 = op2->words[26];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[26] = tempres;

	temp1 = op1->words[27];
	temp2 = op2->words[27];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[27] = tempres;

	temp1 = op1->words[28];
	temp2 = op2->words[28];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[28] = tempres;

	temp1 = op1->words[29];
	temp2 = op2->words[29];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[29] = tempres;

	temp1 = op1->words[30];
	temp2 = op2->words[30];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[30] = tempres;

	temp1 = op1->words[31];
	temp2 = op2->words[31];
	__asm__ volatile ("ADC  %0, %1, %2\n\t" :
		"=r"(tempres) :
		"r"(temp1), "r"(temp2)  );
	result->words[31] = tempres;



	return;
}


//subtract op2 from op1 and store it in result
void subtract(big_int* result, const big_int* op1, const big_int* op2) {
	register int i;
	register unsigned int borrow = 0;
	unsigned long long int temp1, temp2;

	for (i = 0; i < LENGTH; i++) {
		temp1 = op1->words[i];
		temp2 = op2->words[i];

		if (borrow) {
			if (temp1 <= temp2) {
				temp1 += MAXWORD;
			} else {
				borrow = 0;
				temp1--;
			}
		}

		if (temp1 < temp2) {
			borrow = 1;
			temp1 += MAXWORD +1;
		}

		result->words[i] = (unsigned int)(temp1 - temp2);
	}
	return;
}




// perform multiplication by 1 or 0
// bit must have the value 1 or 0 for expected result
// when it returns ZERO, this must not be written to
big_int*  bit_mult(big_int* op, int bit ) {
	if (bit == 0)
		return &ZERO;
	else
		return op;
}


// return bit value at a specific position in the big_int
// position must be within bit length of op
int bit_at(const big_int* op, int position) {
	int word_num = position >> 5;
	int position_in_word = position & 0x001F;

	unsigned int word = op->words[word_num];
	return (word >> (position_in_word) & 1);
}


// return the number of significant bits in p
static int bit_length(int p) {
   int result = 0;
   int mask = 0;
   int i = sizeof(int) * 8 - 1;

   for (i; i >= 0; i--) {
      mask = 1 << i;

      if ((mask & p) != 0) {
         break;
      }
   }

   return i + 1;
}

// return the number of significant bits in big int op
int num_bits(const big_int* op) {
	register int i;

	for (i = LENGTH-1; i >=0; i--) {
		if (op->words[i] !=0)
			return bit_length(op->words[i]) + i * 32;
	}
}

//NOT NECESSARY
//USE bit_mult to mod by 2 (get bit at position 0)
void mod(big_int* result, big_int* op, int modulus) {


}



// right shift a big integer by 1, throwing away the LSB
void right_shift_by1(big_int* result, const big_int* op) {
	register int i;
	register int carry = 0;
	register int nextcarry = 0;
	for( i = LENGTH - 1; i >= 0; i--) {
		nextcarry = op->words[i] & 1;
		result->words[i] = (op->words[i] >> 1) | (carry << 31);
		carry = nextcarry;
	}

}

